package config

import (
	"encoding/json"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"io"
	"os"
	"path"
)

var Conf *Config

const (
	gameConfig = "gameConfig.json"
	servers    = "servers.json"
)

type Config struct {
	GameConfig  map[string]GameConfigValue `json:"gameConfig"`
	ServersConf ServersConf                `json:"serversConf"`
}

type ServersConf struct {
	Nats       NatsConfig         `json:"nats" `
	Connector  []*ConnectorConfig `json:"connector" `
	Servers    []*ServersConfig   `json:"servers" `
	TypeServer map[string][]*ServersConfig
}

type ServersConfig struct {
	ID               string `json:"id" `
	ServerType       string `json:"serverType" `
	HandleTimeOut    int    `json:"handleTimeOut" `
	RPCTimeOut       int    `json:"rpcTimeOut" `
	MaxRunRoutineNum int    `json:"maxRunRoutineNum" `
}

type ConnectorConfig struct {
	ID         string `json:"id" `
	Host       string `json:"host" `
	ClientPort int    `json:"clientPort" `
	Frontend   bool   `json:"frontend" `
	ServerType string `json:"serverType" `
}
type NatsConfig struct {
	Url string `json:"url"`
}

type GameConfigValue map[string]any

func InitConfig(configDir string) {
	//实例化Conf
	Conf = new(Config)
	dir, err := os.ReadDir(configDir)
	if err != nil {
		zap.S().Errorf("game conf initConfig err:%v", err)
	}
	for _, entry := range dir {
		configFile := path.Join(configDir, entry.Name())
		if entry.Name() == gameConfig {
			ReadGameConfig(configFile)
		}
		if entry.Name() == servers {
			ReadServersConfig(configFile)
		}
	}
	TypeServersConfig()
}

/*
*
拼接带type的serversConfig
*/
func TypeServersConfig() {
	if len(Conf.ServersConf.Servers) > 0 {
		if Conf.ServersConf.TypeServer == nil {
			Conf.ServersConf.TypeServer = make(map[string][]*ServersConfig)
		}
		for _, server := range Conf.ServersConf.Servers {
			if Conf.ServersConf.TypeServer[server.ServerType] == nil {
				Conf.ServersConf.TypeServer[server.ServerType] = make([]*ServersConfig, 0)
			}
			Conf.ServersConf.TypeServer[server.ServerType] = append(Conf.ServersConf.TypeServer[server.ServerType], server)
		}
	}
}

/*
*
读取game的配置
*/
func ReadGameConfig(configFile string) {
	//viper的方式会将配置文件key都强制转为小写
	/*
		gameConf := make(map[string]GameConfigValue)
		v := viper.New()
		v.SetConfigFile(configFile)
		v.WatchConfig()
		v.OnConfigChange(func(in fsnotify.Event) {
			err := v.Unmarshal(&gameConf)
			if err != nil {
				panic(fmt.Errorf("读取gameJson配置文件:Unmarshal change game data,err:%v \n", err))
			}
			Conf.GameConfig = gameConf //设置到Conf上
		})
		err := v.ReadInConfig()
		if err != nil {
			panic(fmt.Errorf("读取gameJson配置文件错误:%v\n", err))
		}
		//解析配置文件
		err = v.Unmarshal(&gameConf)
		if err != nil {
			panic(fmt.Errorf("解析gameJson配置文件失败:%v\n", err))
		}
		Conf.GameConfig = gameConf*/

	//直接读取文件的方式
	file, err := os.Open(configFile)
	if err != nil {
		panic(err)
	}
	defer file.Close()
	data, err := io.ReadAll(file)
	if err != nil {
		panic(err)
	}
	gc := make(map[string]GameConfigValue)
	err = json.Unmarshal(data, &gc)
	if err != nil {
		panic(err)
	}
	Conf.GameConfig = gc
}

/*
*
读取server的config
*/
func ReadServersConfig(configFile string) {
	var serversConf ServersConf
	v := viper.New()
	v.SetConfigFile(configFile)
	v.WatchConfig()
	v.OnConfigChange(func(in fsnotify.Event) {
		err := v.Unmarshal(&serversConf)
		if err != nil {
			panic(fmt.Errorf("serverJson配置文件:Unmarshal change game data,err:%v \n", err))
		}
		Conf.ServersConf = serversConf
	})
	err := v.ReadInConfig()
	if err != nil {
		panic(fmt.Errorf("读取serverJson配置文件错误:%v\n", err))
	}
	//解析配置文件
	err = v.Unmarshal(&serversConf)
	if err != nil {
		panic(fmt.Errorf("解析gameJson配置文件失败:%v\n", err))
	}
	Conf.ServersConf = serversConf
}

/*
*
根据serverId获取connector的信息
*/
func (c *Config) GetConnector(serverId string) *ConnectorConfig {
	for _, server := range c.ServersConf.Connector {
		if server.ID == serverId {
			return server
		}
	}
	return nil
}

/*
*
根据serverType的类型获取Connector服务
*/
func (c *Config) GetConnectorByServerType(serverType string) *ConnectorConfig {
	for _, connector := range c.ServersConf.Connector {
		if connector.ServerType == serverType {
			return connector
		}
	}
	return nil
}

/*
*
展示到页面的配置
*/
func (c *Config) GetFrontGameConfig() map[string]any {
	result := make(map[string]any)
	for k, v := range c.GameConfig {
		backend := false
		_, exist := v["backend"]
		if exist {
			backend = v["backend"].(bool) //转成bool的类型
		}
		value, ok := v["value"]
		if ok && !backend {
			result[k] = value
		}
	}
	return result
}
